const MAX_INTERACTIVE_STRING_LENGTH = 500;

export const normalizeWhitespace = (text) => {
  if (typeof text !== 'string') {
    return '';
  }

  return text
    .replace(/\r\n?|\f|\v/g, '\n')
    .replace(/\t+/g, ' ')
    .replace(/\u00a0/g, ' ')
    .replace(/[ \u3000]{2,}/g, ' ')
    .replace(/\n{3,}/g, '\n\n')
    .replace(/ +\n/g, '\n')
    .replace(/\n +/g, '\n')
    .trim();
};

const isPlainObject = (value) => Object.prototype.toString.call(value) === '[object Object]';

const parseJsonSafe = (value) => {
  if (typeof value !== 'string') {
    return null;
  }
  try {
    return JSON.parse(value);
  } catch (_) {
    return null;
  }
};

const toPlainObject = (value) => {
  if (isPlainObject(value)) {
    return value;
  }
  const parsed = parseJsonSafe(value);
  return isPlainObject(parsed) ? parsed : null;
};

const toArray = (value) => {
  if (Array.isArray(value)) {
    return value;
  }
  const parsed = parseJsonSafe(value);
  return Array.isArray(parsed) ? parsed : null;
};

const sanitizeInteractiveElementValue = (value) => {
  if (value === null || value === undefined) {
    return value;
  }

  if (typeof value === 'string') {
    const normalized = normalizeWhitespace(value);
    if (!normalized) {
      return undefined;
    }
    if (normalized.length > MAX_INTERACTIVE_STRING_LENGTH) {
      return `${normalized.slice(0, MAX_INTERACTIVE_STRING_LENGTH)}...`;
    }
    return normalized;
  }

  if (typeof value === 'number' || typeof value === 'boolean') {
    return value;
  }

  if (Array.isArray(value)) {
    return value
      .map((item) => sanitizeInteractiveElementValue(item))
      .filter((item) => item !== undefined);
  }

  if (isPlainObject(value)) {
    const result = {};
    for (const [key, entry] of Object.entries(value)) {
      const sanitized = sanitizeInteractiveElementValue(entry);
      if (sanitized !== undefined) {
        result[key] = sanitized;
      }
    }
    return result;
  }

  return undefined;
};

export const sanitizeChromeInteractiveElementsResult = (payload) => {
  console.log('[MCP][sanitize] raw payload:', payload);

  const fallback = {
    success: false,
    query: '',
    count: 0,
    elements: [],
    totalAvailable: 0,
    truncated: false
  };

  if (!payload) {
    return fallback;
  }

  const outerObject = toPlainObject(payload) ?? (toArray(payload)?.[0] && toPlainObject(toArray(payload)[0]));
  if (!outerObject) {
    return fallback;
  }

  const outerContent = toArray(outerObject.content) ?? outerObject.content;
  const firstOuterEntry = outerContent?.[0];
  const firstOuterText = toPlainObject(firstOuterEntry?.text) ?? parseJsonSafe(firstOuterEntry?.text);
  if (!firstOuterText || firstOuterText.isError) {
    return fallback;
  }

  const dataContent = toArray(firstOuterText?.data?.content) ?? firstOuterText?.data?.content;
  const firstDataEntry = dataContent?.[0];
  const innerText = toPlainObject(firstDataEntry?.text) ?? parseJsonSafe(firstDataEntry?.text);
  if (!innerText) {
    return fallback;
  }

  const success = Boolean(innerText.success);
  const query = sanitizeInteractiveElementValue(innerText.query) ?? '';
  const countValue = Number(innerText.count);
  const count = Number.isFinite(countValue) ? countValue : null;

  const elementsSource = Array.isArray(innerText.elements)
    ? innerText.elements
    : toArray(innerText.elements) ?? [];

  const normalizedElements = elementsSource
    .map((element) => {
      const sanitized = sanitizeInteractiveElementValue(element);
      if (isPlainObject(sanitized)) {
        const { coordinates, ...rest } = sanitized;
        return Object.keys(rest).length ? rest : undefined;
      }
      return sanitized;
    })
    .filter((item) => isPlainObject(item) && Object.keys(item).length);
  const limitedElements = normalizedElements.slice(0, 10);

  const result = {
    success,
    query,
    count: count !== null ? count : limitedElements.length,
    elements: limitedElements,
    totalAvailable: normalizedElements.length,
    truncated: normalizedElements.length > limitedElements.length
  };

  console.log('[MCP][sanitize] normalized result:', result);
  return result;
};
